//
//  JSTFMDBManager.m
//  JSTMobClick
//
//  Created by 01 on 16/8/30.
//  Copyright © 2016年 Czj. All rights reserved.
//

#import "JSTFMDBManager.h"
#import <objc/runtime.h>
#import "FMDB.h"

// 通过实体获取类名
#define KCLASS_NAME(model) [NSString stringWithUTF8String:object_getClassName(model)]

static JSTFMDBManager * manager = nil;
static FMDatabase *db = nil;

@implementation JSTFMDBManager

// 单例
+ (JSTFMDBManager *)sharedInstace
{
    if (manager == nil) {
        manager = [[JSTFMDBManager alloc]init];
    }
    return manager;
}

//生成数据库路径
+ (NSString *)databaseFilePath
{
    NSArray *filePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [filePath objectAtIndex:0];
    //    NSLog(@"%@",filePath);
    NSString *dbFilePath = [documentPath stringByAppendingPathComponent:@"jst.sqlite"];
    //    NSLog(@"home:%@",NSHomeDirectory());
    DLog(@"--------- dbFilePath = %@", dbFilePath);
    return dbFilePath;
}

// 创建数据库
+ (void)creatDatabase
{
    db = [FMDatabase databaseWithPath:[self databaseFilePath]];
}

//创建表
+ (void) createTable:(id)model
{
    //先判断数据库是否存在，如果不存在，创建数据库
    if (!db) {
        [self creatDatabase];
    }
    //判断数据库是否已经打开，如果没有打开，提示失败
    if (![db open]) {
        // NSLog(@"数据库打开失败");
        return;
    }
    
    //为数据库设置缓存，提高查询效率
    [db setShouldCacheStatements:YES];
    
    //判断表是否已经存在
    FMResultSet *rs = [db executeQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?", KCLASS_NAME(model)];
    while ([rs next])
    {
        NSInteger count = [rs intForColumn:@"count"];
        if (0 == count) {
            // 1.创建表语句头部拼接
            NSString *createTabHeaderStr = [NSString stringWithFormat:@"create table %@(id INTEGER PRIMARY KEY", KCLASS_NAME(model)];
            
            // 2.创建表语句中部拼接
            NSString *createTabBodyStr = [NSString string];
            for (int i = 0; i < [self getAllProperties:model].count; i++) {
                createTabBodyStr = [createTabBodyStr stringByAppendingFormat:@",%@ TXTE NOT NULL", [[self getAllProperties:model] objectAtIndex:i]];
            }
            
            // 3.创建表语句尾部拼接
            NSString *createTabTailStr = [NSString stringWithFormat:@")"];
            
            // 4.整句创建表语句拼接
            NSString *createTableStr = [NSString string];
            createTableStr = [createTableStr stringByAppendingFormat:@"%@%@%@",createTabHeaderStr, createTabBodyStr, createTabTailStr];
            DLog(@"---------- create Tab Sql = %@", createTableStr);
            [db executeUpdate:createTableStr];
        }
    }
    //    关闭数据库
    //    [db close];
}

/**
 *  数据库查询所有实体
 */
+ (NSArray *) querySqlforTab:(id)model
{
    [self judgementIsNotOpen:model];
    
    //拼接查询语句
    NSString *selectStr = [NSString stringWithFormat:@"select * from %@", KCLASS_NAME(model)];
    
    DLog(@"---------- query Tab Sql = %@", selectStr);
    
    //定义一个可变数组，用来存放查询的结果，返回给调用者
    NSMutableArray *arr = [NSMutableArray array];
    
    //定义一个结果集，存放查询的数据
    FMResultSet *set = [db executeQuery:selectStr];
    
    //判断结果集中是否有数据，如果有则取出数据
    while ([set next]) {
        // 用id类型变量的类去创建对象
        id modelResult = [[[model class] alloc] init];
        for ( int i = 0; i < [self getAllProperties:model].count; i++) {
            [modelResult setValue:[set stringForColumn:[[self getAllProperties:model] objectAtIndex:i]] forKey:[[self getAllProperties:model] objectAtIndex:i]];
        }
        //将查询到的数据放入数组中。
        [arr addObject:modelResult];
    }
    // 关闭数据库
    [db close];
    
    return arr;
}

/**
 *  数据库增加或更新实体
 *
 *  @param model 实体
 */
+ (void) insertOrUpdateModelToDatabase:(id)model
{
    [self judgementIsNotOpen:model];
    
    //拼接查询语句的头部
    NSString *selectHearStr = [NSString stringWithFormat:@"select * from %@ where ", KCLASS_NAME(model)];
    //拼接查询语句尾部
    NSString *selectTail = [NSString stringWithFormat:@"%@ = ?", [[self getAllProperties:model] objectAtIndex:0]];
    //完整查询语句拼接
    NSString *selectStr = [NSString string];
    selectStr = [selectStr stringByAppendingFormat:@"%@%@", selectHearStr, selectTail];
    
    FMResultSet *set = [db executeQuery:selectStr, [model valueForKey:[[self getAllProperties:model] objectAtIndex:0]]];
    
    if ([set next]) {
        //拼接更新语句的头部
        NSString *updateHeaderStr = [NSString stringWithFormat:@"update %@ set ", KCLASS_NAME(model)];
        //拼接更新语句的中部
        NSString *updateBodyStr = [NSString string];
        //拼接插入数据
        //        NSString *propertyStr = [NSString string];
        for (int i = 1; i < [self getAllProperties:model].count; i++) {
            NSString *str = [model valueForKey:[[self getAllProperties:model] objectAtIndex:i]];
            updateBodyStr = [updateBodyStr stringByAppendingFormat:@"%@ = '%@'", [[self getAllProperties:model] objectAtIndex:i], str];
            if (i != [self getAllProperties:model].count - 1) {
                updateBodyStr = [updateBodyStr stringByAppendingFormat:@", "];
            }
        }
        //拼接更新语句的结尾
        NSString *updateTailStr = [NSString stringWithFormat:@" where %@ = '%@'", [[self getAllProperties:model] objectAtIndex:0], [model valueForKey:[[self getAllProperties:model] objectAtIndex:0]]];
        
        //完整拼接更新语句
        NSString *updateStr = [NSString string];
        updateStr = [updateStr stringByAppendingFormat:@"%@%@%@", updateHeaderStr, updateBodyStr, updateTailStr];
        DLog(@"------- update Tab Sql = %@", updateStr);
        
        BOOL isUpdate = [db executeUpdate:updateStr];
        if (isUpdate) {
            DLog(@"---------更新成功！！！");
        }else DLog(@"---------更新失败！！！");
    }
    //向数据库中插入一条数据
    else
    {
        //拼接插入语句的头部
        NSString *insertHeaderStr = [NSString stringWithFormat:@"INSERT INTO %@ (", KCLASS_NAME(model)];
        //拼接插入语句的中部1
        NSString *insertBodyStr1 = [NSString string];
        for (int i = 0; i < [self getAllProperties:model].count; i++) {
            
            insertBodyStr1 = [insertBodyStr1 stringByAppendingFormat:@"%@", [[self getAllProperties:model] objectAtIndex:i]];
            if (i != [self getAllProperties:model].count - 1) {
                insertBodyStr1 = [insertBodyStr1 stringByAppendingString:@","];
            }
            
        }
        //拼接插入语句的中部2
        NSString *insertBodyStr2 = [NSString stringWithFormat:@") VALUES ("];
        //拼接插入语句的中部3
        NSString *insertBodyStr3 = [NSString string];
        //拼接插入数据
        NSString *propertyStr = [NSString string];
        for (int i = 0; i < [self getAllProperties:model].count; i++) {
            NSString *str = [NSString stringWithFormat:@"%@", [model valueForKey:[[self getAllProperties:model] objectAtIndex:i]]];
            if (str == nil) {
                str = @"none";
            }
            insertBodyStr3 = [insertBodyStr3 stringByAppendingFormat:@"'%@'", str];
            if (i != [self getAllProperties:model].count - 1) {
                insertBodyStr3 = [insertBodyStr3 stringByAppendingFormat:@", "];
            }
        }
        //拼接插入语句的尾部
        NSString *insertTailStr = [NSString stringWithFormat:@")"];
        //完整插入语句拼接
        NSString *insertStr = [NSString string];
        insertStr = [insertStr stringByAppendingFormat:@"%@%@%@%@%@%@", insertHeaderStr, insertBodyStr1, insertBodyStr2, insertBodyStr3, insertTailStr, propertyStr];
        DLog(@"-------- insert Tab Sql = %@", insertStr);
        
        BOOL isInsert = [db executeUpdate:insertStr];
        if (isInsert) {
            DLog(@"-------插入成功！！！");
        }else {
            DLog(@"------插入失败！！！");
        }
    }
    [db close];
}

/**
 *  数据库对应实体
 *
 *  @param model 实体
 */
+ (void)deleteModelInDatabase:(id)model
{
    // 判断是否创建数据库
    if (!db) {
        [self creatDatabase];
    }
    // 判断数据是否已经打开
    if (![db open]) {
        //NSLog(@"数据库打开失败");
        return;
    }
    // 设置数据库缓存，优点：高效
    [db setShouldCacheStatements:YES];
    
    // 判断是否有该表
    if(![db tableExists:KCLASS_NAME(model)])
    {
        return;
    }
    // 删除操作
    // 拼接删除语句
    // delete from tableName where userId = ?
    
    NSString *deletStr = [NSString stringWithFormat:@"delete from %@ where %@ = ?",KCLASS_NAME(model),[[self getAllProperties:model] objectAtIndex:0]];
    [db executeUpdate:deletStr, [model valueForKey:[[self getAllProperties:model] objectAtIndex:0]]];
    // 关闭数据库
    [db close];
}

/**
 *  传递一个model实体
 *
 *  @param model 实体
 *
 *  @return 实体的属性
 */
+ (NSArray *)getAllProperties:(id)model
{
    u_int count;
    
    objc_property_t *properties  = class_copyPropertyList([model class], &count);
    
    NSMutableArray *propertiesArray = [NSMutableArray array];
    
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertiesArray addObject: [NSString stringWithUTF8String: propertyName]];
    }
    
    free(properties);
    return propertiesArray;
}

+ (void) judgementIsNotOpen:(id)model
{
    //先判断数据库是否存在，如果不存在，创建数据库
    if (!db) {
        [self creatDatabase];
    }
    //判断数据库是否已经打开，如果没有打开，提示失败
    if (![db open]) {
        // NSLog(@"数据库打开失败");
        return;
    }
    
    //为数据库设置缓存，提高查询效率
    [db setShouldCacheStatements:YES];
    
    //判断表是否已经存在
    FMResultSet *rs = [db executeQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?", KCLASS_NAME(model)];
    while ([rs next]) {
        NSInteger count = [rs intForColumn:@"count"];
        if (0 == count) {
            [self createTable:model];
        }
    }
}

@end
